#include "tcpServer.hpp"
#include <memory>

using namespace std;
using namespace tcpserver;

static void Usage(const std::string &proc)
{
    cerr << "Usage: \t\n"
         << proc << "port\n\n";
}

bool cal(const Request &req, Response &resp)
{
    // req已经有结构化完成的数据，可以直接使用
    resp._exitcode = OK;
    resp._result = OK;

    switch (req._op)
    {
    case '+':
        resp._exitcode = req._x + req._y;
        break;
    case '-':
        resp._exitcode = req._x - req._y;
        break;
    case '*':
        resp._exitcode = req._x * req._y;
        break;
    case '/':
    {
        if (req._y == 0)
            resp._exitcode = DIV_ZERO;
        else
            resp._exitcode = req._x / req._y;
    }

    break;
    case '%':
    {
        if (req._y == 0)
            resp._exitcode = MOD_ZERO;
        else
            resp._exitcode = req._x % req._y;
    }
    break;
    default:
        resp._exitcode = OP_ERROR;
        break;
    }

    return true;
}

void calculate(Connection *conn)
{
    std::string onePackage;
    // 读取一个完整的报文
    while (ParseOnePackage(conn->_inbuffer, &onePackage))
    {
        // 去掉报头，得到序列化数据 -------"x op y"
        std::string reqStr;
        if (!deLength(onePackage, &reqStr))
            return;
        std::cout << "去掉报头的正文:\n"
                  << reqStr << std::endl;

        // 对请求Request，反序列化
        // 得到一个结构化的请求对象--------req
        Request req;
        if (!req.deserialize(reqStr))
            return;
        
        // 进行计算
        Response resp;
        cal(req, resp);

        //得到序列化数据 ------------"exitcode result"
        std::string respStr;
        resp.serialize(&respStr);

        // 然后我们在发送响应
        // 构建成为一个完整的报文 ----"content_len"\r\n"exitcode result"\r\n
        conn->_outbuffer += enLength(respStr);

        std::cout << "result: " << conn->_outbuffer << std::endl;

        // 直接发
        if (conn->_sender)
            conn->_sender(conn);
    }
}

int main(int argc, char *argv[])
{
    // if (argc != 2)
    // {
    //     Usage(argv[0]);
    //     exit(USAGE_ERR);
    // }

    // uint16_t port = atoi(argv[1]);

    // unique_ptr<tcpServer> tsvr(new tcpServer(calculate, port));
    unique_ptr<tcpServer> tsvr(new tcpServer(calculate));

    tsvr->initServer();
    tsvr->Dispatcher();
    return 0;
}